package com.xmhmyh.generalframework.project.sys.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xmhmyh.generalframework.common.BaseServiceImpl;
import com.xmhmyh.generalframework.common.constants.Constants;
import com.xmhmyh.generalframework.common.conversion.Bean2SelectConverter;
import com.xmhmyh.generalframework.common.enums.ResponseCode;
import com.xmhmyh.generalframework.common.enums.YesOrNo;
import com.xmhmyh.generalframework.common.utils.MyBeanUtils;
import com.xmhmyh.generalframework.common.vo.SelectVO;
import com.xmhmyh.generalframework.framework.exceptions.ManageExceptions;
import com.xmhmyh.generalframework.framework.exceptions.WxExceptions;
import com.xmhmyh.generalframework.project.sys.conversion.User2UserVOConversion;
import com.xmhmyh.generalframework.project.sys.dto.UserDTO;
import com.xmhmyh.generalframework.project.sys.entity.*;
import com.xmhmyh.generalframework.project.sys.enums.UserStatus;
import com.xmhmyh.generalframework.project.sys.mapper.UserMapper;
import com.xmhmyh.generalframework.project.sys.service.*;
import com.xmhmyh.generalframework.project.sys.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: 于丁
 * @DateTime: 2020/7/24 9:09 上午
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private IUserRoleService userRoleService;

    @Autowired
    private IRoleService roleService;


    @Override
    public void saveHandler(User currUser, UserDTO userDTO) {
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        // 判断用户名是否重复
        if (userNameIsRepeat(userDTO.getUserName(), user.getId())) {
            throw new ManageExceptions(ResponseCode.USER_REPEAT);
        }
        // 判断是否为新增
        if (user.getId() == null) {
            // 新增标识
            MyBeanUtils.setSysInfo(user, currUser.getId(), currUser.getAccountId());
            user.setId(uidGenerator.getUID());
            user.setStatus(UserStatus.ACTIVE.getValue());
            user.setPassword(bCryptPasswordEncoder.encode(Constants.DEFAULT_PASSWORD));
            save(user);
        } else {
            User old = getById(user.getId());
            if (old == null) {
                throw new ManageExceptions(ResponseCode.ENTITY_NOT_FIND);
            }
            MyBeanUtils.updateSysInfo(user, user.getId());
            user.setId(old.getId());
            user.setCreateBy(old.getCreateBy());
            user.setEnabled(old.getEnabled());
            user.setCreateTime(old.getCreateTime());
            updateById(user);
        }
        // 更新用户的角色
        updateUserRole(userDTO, user);
    }


    /**
     * @Author: 于丁
     * @Description: 更新用户角色
     * @DateTime: 2021/5/12 5:31 下午
     * @Params: * @param: null
     * @Return {@link null}
     */
    private void updateUserRole(UserDTO userDTO, User user) {
        // 删除用户之前的角色
        LambdaQueryWrapper<UserRole> userRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userRoleLambdaQueryWrapper.eq(UserRole::getUserId, user.getId());
        userRoleService.remove(userRoleLambdaQueryWrapper);
        // 设置user role
        List<UserRole> userRoleList = new ArrayList<>();
        if (userDTO.getRoleIds().size() > 0) {
            for (Long roleId : userDTO.getRoleIds()) {
                userRoleList.add(new UserRole(user.getId(), roleId));
            }
            userRoleService.saveBatch(userRoleList);
        }
    }


    /**
     * @Author: 于丁
     * @Description: 根据用户名判断是否重复
     * @DateTime: 2020/7/30 6:41 下午
     * @Params:
     * @Return
     */
    private Boolean userNameIsRepeat(String userName, Long id) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName, userName);
        if (id != null) {
            queryWrapper.ne(User::getId, id);
        }
        queryWrapper.eq(User::getUserName, userName);
        return count(queryWrapper) > 0 ? true : false;
    }

    @Override
    public UserVO loadMoreHandler(Long id) {
        User user = getById(id);
        if (user == null) {
            throw new ManageExceptions(ResponseCode.USER_NOTFOUND);
        }
        UserVO userVO = User2UserVOConversion.conversion(user);
        // 获取用户的角色
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, user.getId());
        List<UserRole> userRoleList = userRoleService.list(queryWrapper);
        List<Long> roleIds = userRoleList.stream().map(userRole -> {
            return userRole.getRoleId();
        }).collect(Collectors.toList());
        userVO.setRoleIds(roleIds);
        return userVO;
    }

    @Override
    public void activeHandler(Long id) {
        User user = getById(id);
        if (user == null) {
            throw new ManageExceptions(ResponseCode.USER_NOTFOUND);
        }
        user.setStatus(UserStatus.ACTIVE.getValue());
        updateById(user);
    }

    @Override
    public void freezeHandler(Long id) {
        User user = getById(id);
        if (user == null) {
            throw new ManageExceptions(ResponseCode.USER_NOTFOUND);
        }
        user.setStatus(UserStatus.FREEZE.getValue());
        updateById(user);
    }

    @Override
    public void resetPwdHandler(Long id) {
        User user = getById(id);
        if (user == null) {
            throw new ManageExceptions(ResponseCode.USER_NOTFOUND);
        }
        user.setPassword(bCryptPasswordEncoder.encode(Constants.DEFAULT_PASSWORD));
        updateById(user);
    }

    @Override
    public void delHandler(Long id) {
        User user = getById(id);
        if (user == null) {
            throw new ManageExceptions(ResponseCode.USER_NOTFOUND);
        }
        if (user.getIsAdmin() == YesOrNo.YES.getValue()) {
            throw new ManageExceptions(ResponseCode.SUPER_ADMIN_NO_DELETE);
        }
        // 删除user role
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, user.getId());
        userRoleService.remove(queryWrapper);
        // 删除User
        removeById(user.getId());
    }


    @Override
    public User creatUser(String userName, String name, Long accountId, String roleCode, YesOrNo yesOrNo, YesOrNo isShow) {
        // 判断用户名是否重复
        if (checkUserNameRepeat(userName, null)) {
            throw new ManageExceptions(ResponseCode.USER_REPEAT);
        }
        User user = new User();
        MyBeanUtils.setSysInfo(user, null, accountId);
        user.setId(uidGenerator.getUID());
        user.setStatus(UserStatus.ACTIVE.getValue());
        user.setIsAdmin(yesOrNo.getValue());
        user.setIsShow(isShow.getValue());
        user.setName(name);
        user.setPassword(bCryptPasswordEncoder.encode(Constants.DEFAULT_PASSWORD));
        user.setUserName(userName);
        List<UserRole> userRoleList = new ArrayList<>();
        Role role = roleService.getByCode(roleCode);
        if (role == null) {
            throw new WxExceptions(ResponseCode.ROLE_NO_FOUND);
        }
        UserRole userRole = new UserRole(user.getId(), role.getId());
        userRoleService.save(userRole);
        save(user);
        return user;
    }

    @Override
    public void changeUserRole(Long userId, List<String> roleCodeList) {
        User user = getNotNullById(userId);
        LambdaQueryWrapper<UserRole> userRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userRoleLambdaQueryWrapper.eq(UserRole::getUserId, user.getId());
        userRoleService.remove(userRoleLambdaQueryWrapper);
        // 设置user role
        List<UserRole> userRoleList = new ArrayList<>();
        for (String roleCode : roleCodeList) {
            Role role = roleService.getByCode(roleCode);
            if (role != null) {
                userRoleList.add(new UserRole(user.getId(), role.getId()));
            }
        }
        userRoleService.saveBatch(userRoleList);
    }

    @Override
    public Boolean checkUserNameRepeat(String userName, Long userId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName, userName);
        if (userId != null) {
            queryWrapper.ne(User::getId, userId);
        }
        return count(queryWrapper) > 0 ? true : false;
    }

    @Override
    public void removeByAccountId(Long accountId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getAccountId, accountId);
        remove(queryWrapper);
    }


    @Override
    public void resetPassword(Long userId) {
        User user = getNotNullById(userId);
        user.setPassword(bCryptPasswordEncoder.encode(Constants.DEFAULT_PASSWORD));
        updateById(user);
    }

    @Override
    public void modifyPwdHandler(Long userId, String oldPwd, String newPwd) {
        User user = getById(userId);
        if (user == null) {
            throw new WxExceptions(ResponseCode.USER_NOTFOUND);
        }
        if (!bCryptPasswordEncoder.matches(oldPwd, user.getPassword())) {
            throw new ManageExceptions(ResponseCode.OLD_PASSWORD_ERROR);
        }
        user.setPassword(bCryptPasswordEncoder.encode(newPwd));
        updateById(user);
    }


    @Override
    public List<SelectVO> getUserSelectData(User user) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getAccountId, user.getAccountId());
        queryWrapper.eq(User::getIsAdmin, YesOrNo.NO.getValue());
        List<User> userList = list(queryWrapper);
        List<SelectVO> selectVOList = Bean2SelectConverter.converter(userList, User::getName, User::getId);
        return selectVOList;
    }

    @Override
    public User findByPhone(String phone) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName, phone);
        queryWrapper.eq(User::getStatus, UserStatus.ACTIVE.getValue());
        User user = getOne(queryWrapper);
        return user;
    }
}
